#ifndef BAS_BAS_CONTAINER_H
#define BAS_BAS_CONTAINER_H

#include <stdbool.h>
#include <stdarg.h>
#include <stdlib.h>
#include "bas/bas_const.h"
#include "bas/bas_iterator.h"

/**
 * 容器库是否使用日志
 */
#define BAS_CONTAINER_USE_LOG

#ifdef BAS_CONTAINER_USE_LOG
    #include "bas/bas_logger.h"
    #define CONTAINER_LOG_INFO(...)  LOG_INFO(__VA_ARGS__)
    #define CONTAINER_LOG_FATAL(...) LOG_FATAL(__VA_ARGS__)
    #define CONTAINER_LOG_ERROR(...) LOG_ERROR(__VA_ARGS__)
    #define CONTAINER_LOG_WARN(...)  LOG_WARN(__VA_ARGS__)
    #define CONTAINER_LOG_DEBUG(...) LOG_DEBUG(__VA_ARGS__)
#else
    #define CONTAINER_LOG_INFO(...)
    #define CONTAINER_LOG_FATAL(...)
    #define CONTAINER_LOG_ERROR(...)
    #define CONTAINER_LOG_WARN(...)
    #define CONTAINER_LOG_DEBUG(...)
#endif

typedef bool (*T_IteratorIsValid)(const T_Iterator);
typedef void (*T_IteratorGetValueFunction)(const T_Iterator, void *);
typedef void *(*T_IteratorGetPointerFunction)(const T_Iterator);
typedef void (*T_IteratorSetValueFunction)(T_Iterator, const void *);
typedef T_Iterator (*T_IteratorNextFunction)(const T_Iterator);
typedef T_Iterator (*T_IteratorPrevFunction)(const T_Iterator);
typedef bool (*T_IteratorEqualFunction)(const T_Iterator, const T_Iterator);
typedef bool (*T_IteratorLessFunction)(const T_Iterator, const T_Iterator);
typedef T_Iterator (*T_IteratorNextNFunction)(const T_Iterator, const size_t nCount);
typedef T_Iterator (*T_IteratorPrevNFunction)(const T_Iterator, const size_t nCount);
typedef int (*T_IteratorMinusFunction)(const T_Iterator, const T_Iterator);

/**
 * 迭代器回调函数表
 */
typedef struct T_IteratorCallBackTable_tag
{
    T_IteratorIsValid            pfnIsValid;    ///<判断迭代器是否有效的额外检查
    T_IteratorGetValueFunction   pfnGetValue;   ///<取值函数
    T_IteratorGetPointerFunction pfnGetPointer; ///<取指针函数
    T_IteratorSetValueFunction   pfnSetValue;   ///<设值函数
    T_IteratorNextFunction       pfnNext;       ///<取下一个迭代器
    T_IteratorPrevFunction       pfnPrev;       ///<取上一个迭代器
    T_IteratorEqualFunction      pfnEqual;      ///<判断迭代是否相等
    T_IteratorLessFunction       pfnLess;       ///<判断第一个迭代器是否小于第二个
    T_IteratorNextNFunction      pfnNextN;      ///<取下N个迭代器
    T_IteratorPrevNFunction      pfnPrevN;      ///<取上N个迭代器
    T_IteratorMinusFunction      pfnMinus;      ///<取两个迭代器的差
} T_IteratorCallBackTable;

/**
 * 容器抽象类
 * @note 所有的容器结构体必须要包含下列域,并且顺序要完全一致
 */
typedef struct T_Container_tag
{
    T_IteratorCallBackTable *ptCallBackTable;     ///<迭代器回调函数表指针
} T_Container;

/**
 * 数据类型
 */
#define BUILDIN_STRING      1
#define BUILDIN_CHAR        2
#define BUILDIN_BOOL        3
#define BUILDIN_SHORT       4
#define BUILDIN_INT         5
#define BUILDIN_LONG        6
#define BUILDIN_LONGLONG    7
#define BUILDIN_FLOAT       8
#define BUILDIN_DOUBLE      9
#define BUILDIN_LONGDOUBLE 10

typedef void (*T_DestroyFunction)(void *);
typedef int (*T_CopyFunction)(void *, const void *);
typedef bool (*T_CompareFunction)(const void *, const void *);
typedef int (*T_InitFunction)(void *, void *);

/**
 * 类型信息
 */
typedef struct T_TypeInfo_tag
{
    int               iDataType;   ///<数据类型, 0表示用户自定义的结构体类型
    size_t            nTypeSize;   ///<类型大小
    T_DestroyFunction pfnDestroy;  ///<销毁函数
    T_CopyFunction    pfnCopy;     ///<拷贝函数
    T_CompareFunction pfnLess;     ///<小于比较函数
    T_InitFunction    pfnInit;     ///<初始化函数
} T_TypeInfo;

/**
 * @brief     创建类型信息
 * @param[in] caTypeName 类型名
 * @param[in] nTypeSize  类型大小
 * @param[in] pfnDestory 第一个可选参数为销毁函数指针, 类型为T_DestroyFunction
 * @param[in] pfnCopy    第二个可选参数为拷贝函数指针, 类型为T_CopyFunction
 * @param[in] pfnLess    第三个可选参数为小于比较函数指针, 类型为T_CompareFunction
 * @param[in] pfnInit    第四个可选参数为初始化函数指针, 类型为T_InitFunction
 * @note      1.可选参数列表必须以BAS_PARM_END结尾
 *            2.本函数为内部函数, 不应该直接调用本函数, 应使用_T()宏
 *            3.如果你需要一个销毁函数, 往往你也需要一个拷贝函数, 否则将会带来内存泄露
 */
T_TypeInfo _basContainerCreateTypeInfo(const char *caTypeName, const size_t nTypeSize, ...);

/**
 * @brief     创建类型信息
 * @param[in] _TypeName 类型名, 可以为BUILDIN_STRING等内置类型, 也可以是用户自定义类型名
 * @param[in] xxx       可选参数同_basContainerCreateTypeInfo
 *                      按顺序依次为销毁函数, 小于比较函数, 拷贝函数, 初始化函数
 */
#define _T(_TypeName, ...) _basContainerCreateTypeInfo(#_TypeName, sizeof(_TypeName), ##__VA_ARGS__, BAS_PARM_END)

/**
 * @brief         根据数据类型从可变参数取值
 * @param[in]     iDataType 数据类型
 * @param[out]    pvOutput  输出缓冲区
 * @param[in,out] varList   可变参数列表
 * @return        0 - 成功 -1 - 失败
 * @note          本函数为内部函数, 不应该直接调用本函数
 */
int  _basContainerGetVaArgValue(const T_TypeInfo *ptTypeInfo, void *pvOutput, va_list *pVarList);

#endif
